package br.com.gscorp.bankLion.init;

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;

import br.com.gscorp.bankLion.security.BankLionAuthenticationEntryPoint;
import br.com.gscorp.bankLion.security.BankLionAuthenticationFailureHandler;
import br.com.gscorp.bankLion.security.BankLionAuthenticationProvider;
import br.com.gscorp.bankLion.security.BankLionAuthenticationSuccessHandler;
import br.com.gscorp.bankLion.security.BankLionLogoutSuccessHandler;
import br.com.gscorp.bankLion.security.BankLionWebAuthenticationDetailsSource;

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = "br.com.gscorp.bankLion")
public class SecurityContext extends WebSecurityConfigurerAdapter {
	
	@Autowired
	private BankLionAuthenticationProvider bankLionAuthenticationProvider;

	@Autowired
	private BankLionAuthenticationSuccessHandler bankLionAuthenticationSuccessHandler;

	@Autowired
	private BankLionAuthenticationFailureHandler bankLionAuthenticationFailureHandler;

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.authenticationProvider(bankLionAuthenticationProvider);
	}
	
	@Autowired
    private ApplicationContext context;

    @Bean
	public JsonFactory jsonFactory() {
		return new JsonFactory(new ObjectMapper());
	}
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    	this.configureLogin(http);
    	this.configureEntryPoint(http);
    	this.configureLogout(http);
    	this.configureCsrf(http);
    	this.configureSession(http);
    }

    private HttpSecurity configureLogin(HttpSecurity http) throws Exception {
    	return http.formLogin().loginProcessingUrl("/api/login")
		.successHandler(bankLionAuthenticationSuccessHandler)
		.failureHandler(bankLionAuthenticationFailureHandler)
		.authenticationDetailsSource(new BankLionWebAuthenticationDetailsSource())
		.and();
	}
    
    private HttpSecurity configureCsrf(HttpSecurity http) throws Exception {
		return http.csrf().disable();
	}

	private HttpSecurity configureSession(HttpSecurity http) throws Exception {
		return http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS).and();
	}

	private HttpSecurity configureEntryPoint(HttpSecurity http)
			throws Exception {
		return http.exceptionHandling()
				.authenticationEntryPoint(new BankLionAuthenticationEntryPoint())
				.and();
	}

	private HttpSecurity configureLogout(HttpSecurity http) throws Exception {
		return http.logout().logoutUrl("/api/logout")
				.logoutSuccessHandler(new BankLionLogoutSuccessHandler()).and();
	}
	
	@Bean(name="authenticationManager")
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManager();
	}

}
